package bpel2rep.version.store.impl;

import static org.junit.Assert.*;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Properties;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import org.eclipse.emf.teneo.PersistenceOptions;
import org.eclipse.emf.teneo.hibernate.HbDataStore;
import org.eclipse.emf.teneo.hibernate.HbHelper;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import executable.ExecutablePackage;
import executable.TProcess;

import bpel2rep.exception.DuplicateVersionException;
import bpel2rep.process.ProcessPackage;
import bpel2rep.process.impl.ProcessFactoryImpl;
import bpel2rep.version.MetaInfo;
import bpel2rep.version.StateName;
import bpel2rep.version.Version;
import bpel2rep.version.VersionFactory;
import bpel2rep.version.VersionId;
import bpel2rep.version.VersionPackage;
import bpel2rep.version.impl.VersionFactoryImpl;
import bpel2rep.version.state.Free;
import bpel2rep.version.state.impl.FreeImpl;
import bpel2rep.version.store.StoreFactory;
import bpel2rep.version.store.TeneoStore;

public class TeneoStoreImplTest {
	private TeneoStore ts;
	private VersionFactory vf;

	@Before
	public void setUp() throws Exception {
		bpel2rep.version.store.StoreFactory f = bpel2rep.version.store.StoreFactory.eINSTANCE;
		this.ts = f.createTeneoStore();
		this.vf = bpel2rep.version.VersionFactory.eINSTANCE;
	}

	@After
	public void tearDown() throws Exception {
	}

	
//	@Test
//	public void orphanTest(){
//		final String dataStoreName = "bpel2rep";
//		HbDataStore datastore = HbHelper.INSTANCE.createRegisterDataStore(dataStoreName);
//		Properties props = new Properties();
//		props.setProperty("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
//		props.setProperty("hibernate.connection.url", "jdbc:mysql://localhost/bpeltest");
//		props.setProperty("hibernate.connection.username", "root");
//		props.setProperty("hibernate.connection.password", "");
//		props.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
//		props.setProperty("hibernate.max_fetch_depth", "1");
//		props.setProperty(PersistenceOptions.INHERITANCE_MAPPING, "JOINED");
//		// set lazy load false. 
//		props.setProperty(PersistenceOptions.FETCH_CONTAINMENT_EAGERLY, "true");
//		//props.setProperty(PersistenceOptions.USE_MAPPING_FILE, "true");
//		datastore.setProperties(props);
//
//		datastore.setEPackages(new EPackage[] { ProcessPackage.eINSTANCE,
//				ExecutablePackage.eINSTANCE, VersionPackage.eINSTANCE });
//		datastore.initialize();
//		SessionFactory sf = datastore.getSessionFactory();
//		Session session = sf.openSession();
//		
//		session.beginTransaction();
//		Query q = session.createQuery("FROM Version v WHERE v.process.id='"
//				+ "637f7c77-5858-41b1-97d5-3216f4357450" + "'");
//		List<bpel2rep.version.Version> vs = q.list();
//		bpel2rep.version.Version v = (bpel2rep.version.Version) vs.get(0);
//		v.getMetaInfo().setDescription("bla description");
//		session.update(v);
//		session.getTransaction().commit();
//		session.close();
		//v.getMetaInfo().setDescription("bla2");
//		Session s2 = sf.openSession();
//		s2.beginTransaction();
//		s2.update(v);
//		s2.getTransaction().commit();
//		s2.close();
		
//	}
//	
//	@Test
//	public void testUpdate() {
//		// get a version, change sth and update it.
//		VersionId vid = VersionFactory.eINSTANCE.createVersionId();
//		vid.setMajorID(1);
//		vid.setMinorID(0);
//		try {
//			Version v = ts.retrieve("9417d17c-f256-4f64-86f6-8c146fc0f087", vid);
//			
///*			TProcess tp = v.getProcess().getTprocess();
//			tp.getAssign();
//			*/
////			ts.update(v);
//		} catch (Exception e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//	}
	@Test
	public void testSave() {
		MetaInfo info = vf.createMetaInfo();
		info.setDescription("this is 1. test");
		info.setId("tiw_1");
		info.setName("tiw_test");
		// get a TProcess
		String xmlFile = "sampleprocesses/HelloWorld2.bpel";
		executable.util.ExecutableXMLProcessor processor = null;
		Resource resource = null;
		try {
			processor = new executable.util.ExecutableXMLProcessor();
			resource = processor
					.load(new File(xmlFile).getAbsolutePath(), null);
		} catch (Exception e) {
			e.printStackTrace();
		}
		EList<EObject> eos = resource.getContents();
		executable.impl.DocumentRootImpl dri = (executable.impl.DocumentRootImpl) eos
				.get(0);
		executable.TProcess tp = dri.getProcess();

		Version v = vf.initVersion(tp, info);
		assertTrue (v.getVersionId().getMajorID() == 1);
		assertTrue (v.getVersionId().getMinorID() == 0);
//		assertTrue (v.getVersionState().getClass() == bpel2rep.version.state.Free.class);
		ts.save(v);
		System.out.println(v.getProcess().getId());
	}

	@Test
	public void testRetrieve() {
		//create a new version
		MetaInfo info = vf.createMetaInfo();
		info.setDescription("this is 1. test");
		info.setId("tiw_1");
		info.setName("tiw_test");
		// get a TProcess
		String xmlFile = "sampleprocesses/HelloWorld2.bpel";
		executable.util.ExecutableXMLProcessor processor = null;
		Resource resource = null;
		try {
			processor = new executable.util.ExecutableXMLProcessor();
			resource = processor
					.load(new File(xmlFile).getAbsolutePath(), null);
		} catch (Exception e) {
			e.printStackTrace();
		}
		EList<EObject> eos = resource.getContents();
		executable.impl.DocumentRootImpl dri = (executable.impl.DocumentRootImpl) eos
				.get(0);
		executable.TProcess tp = dri.getProcess();

		Version v = vf.initVersion(tp, info);
		
		ts.save(v);
		
		bpel2rep.version.Version v2 = ts
				.retrieve(v.getProcess().getId());
		assertTrue ("name of metainfo is:" + v2.getMetaInfo().getName(), v2.getMetaInfo().getName().equals("tiw_test"));
		assertTrue("state name is: " + v2.getStateName().toString(), v2.getStateName() == StateName.INITIAL);

		// create resource set and resource
		ResourceSet resourceSet = new ResourceSetImpl();

		// Register XML resource factory
		resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap()
				.put("xmi", new XMIResourceFactoryImpl());

		Resource resourceVersion = resourceSet.createResource(URI
				.createFileURI("tmp/version.xmi"));
		// add the root object to the resource
		resourceVersion.getContents().add(v2);
		try {
			resourceVersion.save(null);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	
	@Test
	public void testRetrieveWithVersionId() {
		//create a new version
		MetaInfo info = vf.createMetaInfo();
		info.setDescription("this is 1. test");
		info.setId("tiw_1");
		info.setName("tiw_test");
		// get a TProcess
		String xmlFile = "sampleprocesses/HelloWorld2.bpel";
		executable.util.ExecutableXMLProcessor processor = null;
		Resource resource = null;
		try {
			processor = new executable.util.ExecutableXMLProcessor();
			resource = processor
					.load(new File(xmlFile).getAbsolutePath(), null);
		} catch (Exception e) {
			e.printStackTrace();
		}
		EList<EObject> eos = resource.getContents();
		executable.impl.DocumentRootImpl dri = (executable.impl.DocumentRootImpl) eos
				.get(0);
		executable.TProcess tp = dri.getProcess();

		Version v = vf.initVersion(tp, info);
		
		ts.save(v);
		
		
		
		VersionId vid = VersionFactory.eINSTANCE.createVersionId();
		vid.setMajorID(1);
		vid.setMinorID(0);
		bpel2rep.version.Version v2 = null;
		try {
			v2 = ts.retrieve(v.getProcess().getId(), vid);

			assertTrue ("name of metainfo is:" + v2.getMetaInfo().getName(), v2.getMetaInfo().getName().equals("tiw_test"));
			assertTrue("state name is: " + v2.getStateName().toString(), v2.getStateName() == StateName.INITIAL);
//			assertTrue("name of state is: " + v2.getVersionState().getName(), v2.getVersionState().getName() == "FreeImpl");
			// SHOULD BE bpel2rep.version.state.impl.FreeImpl but is VersionStateImpl
			//assertTrue ("state of version is: " + v2.getVersionState().getClass().getName(), v2.getVersionState().getClass() == FreeImpl.class);
			
			// create resource set and resource
			ResourceSet resourceSet = new ResourceSetImpl();

			// Register XML resource factory
			resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap()
					.put("xmi", new XMIResourceFactoryImpl());

			Resource resourceVersion = resourceSet.createResource(URI
					.createFileURI("tmp/version2.xmi"));
			// add the root object to the resource
			resourceVersion.getContents().add(v2);
			try {
				resourceVersion.save(null);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Test
	public void testInStore(){
		Version v = VersionFactoryImpl.eINSTANCE.createVersion();
		bpel2rep.process.Process p = ProcessFactoryImpl.eINSTANCE.createProcess();
		v.setProcess(p);
		v.getProcess().setId("3180fb85-1ed6-46c2-8b05-1317272a99ca");
		VersionId vid = VersionFactory.eINSTANCE.createVersionId();
		vid.setMajorID(1);
		vid.setMinorID(0);
		v.setVersionId(vid);
		try {
			assertTrue(this.ts.inStore(v));
		} catch (DuplicateVersionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		v.getProcess().setId("xxx");
		try {
			assertFalse(this.ts.inStore(v));
		} catch (DuplicateVersionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
